/*
 * ------------------------------------------------------------------------
 *  FECHA      HORA   NOMBRE        COMENTARIO     			     
 * ------------------------------------------------------------------------
 *  14/05/08   20:00  JAVI          Creació métodes implementació              
 *  28/05/08   23:59  ALEX          Implementació de la clase.
 * 
 */

package net.ieslaferreria.infoCiutat;

import java.util.Vector;

/**
 * 
 * @author Alex, Javi, David y Sergio
 */
public class RutaImpl implements Ruta {
    
    /*
     * Variable que conté les arestes que formen la ruta.
     */
    Vector arestes = new Vector();
    /*
     * Variable que conté el punt en el que ens trobem actualment quan reproduim
     * la ruta.
     */
    Punt puntActual;
    /*
     * Variable que conté l'index de la posició de l'aresta actual quan 
     * reproduim la ruta.
     */
    int ind = 0;
    /*
     * Variable que conté el temps total de la ruta.
     */
    int temps = 0;
    /*
     * Variable que conté el temps que deurie haver passat des de que vam 
     * iniciar la ruta.
     */
    int tempsTranscurrit = 0;

    public RutaImpl(Punt puntOrigen){
        this.puntActual = puntOrigen;
    }
    
    public String getInstruccio() {
        String ret = "";
        int gir = 0;
        
        // No hi ha transbord per tant continuem a la mateixa xarxa.
        if (!this.getArestaActual().hiHaTransbord()){
            
            // Si l'aresta pertany a la xarxa de carrers...
            if (this.getArestaActual().getPuntInici().getCodiXarxa() ==
                                               XarxaManager.CODI_XARXA_CARRERS){
                int metres = 0;
                while (this.getArestaActual().getNom() == this.
                                                   getSeguentAresta().getNom()){
                    metres = metres + this.getArestaActual().getDistancia();
                    this.avança();
                }
                ret.concat("Continua ").concat(String.valueOf(metres)).
                                                concat(" metres i gira cap a ");
                gir = this.getGir();
                if (gir > 0){
                    ret.concat("la dreta pel carrer ");
                }else if(gir < 0){
                    ret.concat("l'esquerra pel carrer ");
                }
                ret.concat(this.getArestaActual().getNom());
                
            // Si l'aresta no pertany a la xarxa de carrers...
            }else{
                int parades = 0;
                while (!this.getArestaActual().hiHaTransbord()){
                    parades++;
                    this.avança();
                }
                ret.concat("Continua fins a ").concat(this.getSeguentPunt().
                                                                      getNom());
            } 
            
        // Hi ha transbord i també camviem de xarxa.
        }else if(this.getArestaActual().hiHaTransbord()
                   && this.getArestaActual().hiHaCanviDeXarxa()){
            // Ordenarem el canvi de xarxa
            XarxaManager xarxes = new XarxaManagerImpl(InfoCiutat.db);
            ret.concat("Canviem a la xarxa de ").concat(xarxes.getXarxa(this.
                                           puntActual.getCodiXarxa()).getNom());
        
        // Nomes hi ha transbord pero continuem a la mateixa xarxa.
        } else {
            // Ordenarem el canvi de linia
            ret.concat("Canviem a la linia ").concat(this.puntActual.getLinia());
        }      
        return ret;
    }

    public Aresta getSeguentAresta() {
        return (Aresta)this.arestes.elementAt(ind+1);
    }

    public Aresta getArestaActual() {
        return (Aresta)this.arestes.elementAt(ind);
    }
    
    public Aresta getArestaAnterior() {
        return (Aresta)this.arestes.elementAt(ind-1);
    }

    public int getTempsRestant() {
        return this.temps;
    }

    public void reproduirRuta() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void addAresta(Aresta aresta) {
        this.arestes.addElement(aresta);
        this.temps = this.temps + aresta.getTemps();
    }

    public void avança() {
        this.temps = this.temps - this.getArestaActual().getTemps();
        this.tempsTranscurrit = this.tempsTranscurrit + this.getArestaActual().
                                                                     getTemps();
        this.puntActual = this.getSeguentPunt();
        this.ind++;
    }

    public int getTempsTotal() {
        return this.temps + this.tempsTranscurrit;
    }
    
    /**
     * Retorna la direcció cap a on hem de girar quan arrivem a una cruilla on
     * hem de canviar de direcció.
     * Retornará < 0 en el cas que girem a l'esquerra i > 0 en el cas que girem
     * a la dreta.
     * 
     * @return int
     */
    private int getGir(){
        // ret < 0 -> Girar a l'esquerra
        // ret > 0 -> Girar a la dreta
        // ret = 0 -> ¿No ha entrat a cap condició?
        int ret = 0;
        int vectorX = this.puntActual.getCoordenadaX() - this.getAnteriorPunt().
                                                               getCoordenadaX(); 
        int vectorY = this.puntActual.getCoordenadaY() - this.getAnteriorPunt().
                                                               getCoordenadaY();
        int pendentAnterior = vectorY / vectorX;
        int pendentActual = (this.getSeguentPunt().getCoordenadaY() - 
                             this.puntActual.getCoordenadaY()) / 
                            (this.getSeguentPunt().getCoordenadaX() -
                             this.puntActual.getCoordenadaX());
        //Determinem el quadrant del vector de l'aresta
        if (vectorX > 0){
            if (vectorY > 0){
                if ((pendentActual > pendentAnterior && vectorX > this.
                        getSeguentPunt().getCoordenadaX()) || (pendentActual <
                        pendentAnterior && vectorX < this.getSeguentPunt().
                        getCoordenadaX())){
                    ret = 1;
                }else{
                    ret = -1;
                }
            }else if (vectorY < 0){
                if ((pendentActual < pendentAnterior && vectorX > this.
                        getSeguentPunt().getCoordenadaX()) || (pendentActual >
                        pendentAnterior && vectorX > this.getSeguentPunt().
                        getCoordenadaX())){
                    ret = -1;
                }else{
                    ret = 1;
                }
            }            
        }else if (vectorX < 0){
            if (vectorY > 0){
                if ((pendentActual < pendentAnterior && vectorX < this.
                        getSeguentPunt().getCoordenadaX()) || (pendentActual >
                        pendentAnterior && vectorX > this.getSeguentPunt().
                        getCoordenadaX())){
                    ret = -1;
                }else{
                    ret = 1;
                }
            }else if (vectorY < 0){
                if ((pendentActual > pendentAnterior && vectorX > this.
                        getSeguentPunt().getCoordenadaX()) || (pendentActual <
                        pendentAnterior && vectorX < this.getSeguentPunt().
                        getCoordenadaX())){
                    ret = 1;
                }else{
                    ret = -1;
                }
            }
        }
        return ret;
    }
    
    /**
     * Retorna el punt següent a la nostra ruta.
     * 
     * @return Punt
     */
    private Punt getSeguentPunt(){
        Punt ret = null;
        if(this.puntActual == this.getArestaActual().getPuntInici()){
            ret = this.getArestaActual().getPuntFinal();
        }else{
            ret = this.getArestaActual().getPuntInici();
        }
        return ret;
    }
    
    /**
     * Retorna el punt anterior a la nostra ruta.
     * 
     * @return Punt
     */
    private Punt getAnteriorPunt(){
        Punt ret = null;
        if(this.puntActual == this.getArestaAnterior().getPuntInici()){
            ret = this.getArestaAnterior().getPuntFinal();
        }else{
            ret = this.getArestaAnterior().getPuntInici();
        }
        return ret;
    }
}
